const fs = require('fs');
const path = require('path');
const { SourceMapConsumer } = require('source-map');

// 从命令行获取sourcemap目录
const sourceMapDir = process.argv[2] || './sourcemaps';

// 缓存已加载的sourcemap
const sourceMapCache = new Map();

/**
 * 获取SourceMapConsumer实例
 */
async function getSourceMapConsumer(jsFileName) {
    if (sourceMapCache.has(jsFileName)) {
        return sourceMapCache.get(jsFileName);
    }
    
    // 尝试可能的sourcemap文件名
    const possibleMapFiles = [
        `${jsFileName}.map`,
        path.basename(jsFileName, '.js') + '.map'
    ];
    
    let sourceMapContent = null;
    
    // 查找并读取sourcemap文件
    for (const mapFile of possibleMapFiles) {
        const mapFilePath = path.join(sourceMapDir, mapFile);
        try {
            if (fs.existsSync(mapFilePath)) {
                sourceMapContent = fs.readFileSync(mapFilePath, 'utf8');
                break;
            }
        } catch (e) {
            console.error(`读取sourcemap失败: ${mapFilePath}`, e);
        }
    }
    
    if (!sourceMapContent) {
        console.warn(`未找到${jsFileName}对应的sourcemap文件`);
        return null;
    }
    
    // 解析sourcemap
    try {
        const consumer = await new SourceMapConsumer(sourceMapContent);
        sourceMapCache.set(jsFileName, consumer);
        return consumer;
    } catch (e) {
        console.error(`解析sourcemap失败: ${jsFileName}`, e);
        return null;
    }
}

/**
 * 解析单行堆栈
 */
async function resolveStackLine(line) {
    // 匹配带函数名的堆栈行: at functionName (file.js:1:23)
    const functionRegex = /at (.*?) \((.*?):(\d+):(\d+)\)/;
    const functionMatch = line.match(functionRegex);
    
    if (functionMatch) {
        const [, functionName, fileName, lineNum, colNum] = functionMatch;
        return resolveLocation(functionName, fileName, parseInt(lineNum), parseInt(colNum));
    }
    
    // 匹配不带函数名的堆栈行: at file.js:1:23
    const simpleRegex = /at (.*?):(\d+):(\d+)/;
    const simpleMatch = line.match(simpleRegex);
    
    if (simpleMatch) {
        const [, fileName, lineNum, colNum] = simpleMatch;
        return resolveLocation(null, fileName, parseInt(lineNum), parseInt(colNum));
    }
    
    // 无法解析的行，原样返回
    return line;
}

/**
 * 解析位置信息
 */
async function resolveLocation(functionName, fileName, line, column) {
    const baseFileName = path.basename(fileName);
    const consumer = await getSourceMapConsumer(baseFileName);
    
    if (!consumer) {
        // 无sourcemap，返回原始信息
        return functionName 
            ? `at ${functionName} (${fileName}:${line}:${column})`
            : `at ${fileName}:${line}:${column}`;
    }
    
    // 解析原始位置
    const originalPosition = consumer.originalPositionFor({
        line: line,
        column: column - 1 // 转换为0-based索引
    });
    
    if (!originalPosition.source) {
        // 找不到对应位置
        return functionName 
            ? `at ${functionName} (${fileName}:${line}:${column})`
            : `at ${fileName}:${line}:${column}`;
    }
    
    // 构建解析后的信息
    const originalSource = path.basename(originalPosition.source);
    const originalLine = originalPosition.line || line;
    const originalColumn = (originalPosition.column || column) + 1; // 转回1-based
    const originalName = originalPosition.name || functionName;
    
    return originalName
        ? `at ${originalName} (${originalSource}:${originalLine}:${originalColumn})`
        : `at ${originalSource}:${originalLine}:${originalColumn}`;
}

/**
 * 解析整个错误堆栈
 */
async function resolveStackTrace(stack) {
    const lines = stack.split('\n');
    const resolvedLines = [];
    
    for (const line of lines) {
        resolvedLines.push(await resolveStackLine(line.trim() ? line : ''));
    }
    
    return resolvedLines.join('\n');
}

// 从标准输入读取错误堆栈
let input = '';
process.stdin.on('data', (chunk) => {
    input += chunk;
});

process.stdin.on('end', async () => {
    try {
        const resolvedStack = await resolveStackTrace(input);
        console.log(resolvedStack);
        process.exit(0);
    } catch (error) {
        console.error('解析错误:', error);
        process.exit(1);
    }
});
